﻿#include "Drawer.h"
#include <glm/gtc/type_ptr.hpp>

SharedFramebuffer Drawer::initSharedFramebuffer(int width, int height) {
	SharedFramebuffer m_sharedFB{};
	m_sharedFB.width = width;
	m_sharedFB.height = height;

	// 创建MSAA FBO
	glGenFramebuffers(1, &m_sharedFB.msaaFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, m_sharedFB.msaaFBO);

	// 多重采样颜色缓冲
	glGenRenderbuffers(1, &m_sharedFB.colorRBO);
	glBindRenderbuffer(GL_RENDERBUFFER, m_sharedFB.colorRBO);
	glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, width, height);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_sharedFB.colorRBO);

	// 多重采样深度缓冲
	glGenRenderbuffers(1, &m_sharedFB.depthRBO);
	glBindRenderbuffer(GL_RENDERBUFFER, m_sharedFB.depthRBO);
	glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_sharedFB.depthRBO);

	// 创建解析用FBO和纹理
	glGenFramebuffers(1, &m_sharedFB.resolveFBO);
	glGenTextures(1, &m_sharedFB.colorTex);
	glBindTexture(GL_TEXTURE_2D, m_sharedFB.colorTex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glBindFramebuffer(GL_FRAMEBUFFER, m_sharedFB.resolveFBO);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_sharedFB.colorTex, 0);

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if (status != GL_FRAMEBUFFER_COMPLETE) {
		std::cerr << "FBO Error: 0x" << std::hex << status << std::endl;
	}
	return m_sharedFB;
}

std::vector<DoubleSector> Drawer::initDoubleSector(
        int width, int height,
        float* startAngle, float* endAngle,
        unsigned char* r, unsigned char* g, unsigned char* b, unsigned char a,
        size_t* startDuration, size_t* endDuration, size_t doubleSectorNum,
        float borderBrightness, float centerBrightness, float borderRadius,
        float middleColorLoc
    ) {
	std::vector<DoubleSector> sectors;
	const float centerX = width / 2.0f;
	const float centerY = height / 2.0f;
	constexpr float step = glm::radians(0.1f);
	const float maxRadius = std::max<float>(centerX, centerY);

	for (size_t i = 0; i < doubleSectorNum; ++i) {
		DoubleSector sector;

		// 生成几何数据（与原始代码相同）
		// ... [顶点数据生成代码保持不变] ...
		std::vector<DoubleSectorVertex> vertices;
		float s = startAngle[i];
		float e = endAngle[i];
		float sd = static_cast<float>(startDuration[i]);
		float ed = static_cast<float>(endDuration[i]);
		for (float theta = s; theta <= e; theta += step) {
			vertices.push_back({ theta, 1.0f }); // 外圈
			vertices.push_back({ theta, 0.0f }); // 内圈
		}
		// 确保最后一个点精确到达e
		// if (!vertices.empty() && vertices.back().angle < e) {
		// 	vertices.push_back({ e, 1.0f });
		// 	vertices.push_back({ e, 0.0f });
		// }

		glGenVertexArrays(1, &sector.VAO);
		glGenBuffers(1, &sector.VBO);

		glBindVertexArray(sector.VAO);
		glBindBuffer(GL_ARRAY_BUFFER, sector.VBO);
		glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(DoubleSectorVertex), vertices.data(), GL_STATIC_DRAW);

		// 属性指针
		glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(DoubleSectorVertex), (void*)offsetof(DoubleSectorVertex, angle));
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(DoubleSectorVertex), (void*)offsetof(DoubleSectorVertex, type));
		glEnableVertexAttribArray(1);

		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);

		// 解绑
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);

		// 存储参数
		sector.startDuration = sd;
		sector.endDuration = ed;
		sector.r = r[i];
		sector.g = g[i];
		sector.b = b[i];
		sector.a = a;
		sector.centerX = centerX;
		sector.centerY = centerY;
		sector.maxRadius = maxRadius;
		sector.vertexCount = vertices.size();
		sector.borderBrightness = borderBrightness;
		sector.centerBrightness = centerBrightness;
		sector.borderRadius = borderRadius;
		sector.middleColorLoc = middleColorLoc;
		sector.angleRange[0] = s;
		sector.angleRange[1] = e;

		sectors.push_back(sector);
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	return sectors;
}

void Drawer::drawDoubleSector(GLuint shaderProgram, std::vector<DoubleSector> &doubleSector, size_t currentDuration,
                              SharedFramebuffer &m_sharedFB, float end_radius, float max_radius, int &sectorMinIndex) {
	glBindFramebuffer(GL_FRAMEBUFFER, m_sharedFB.msaaFBO);
	glViewport(0, 0, m_sharedFB.width, m_sharedFB.height);

	// 清除缓冲区（注意保留之前绘制的内容）
	glClear(GL_DEPTH_BUFFER_BIT); // 仅清除深度缓冲
	glEnable(GL_MULTISAMPLE);

	// 设置公共投影矩阵
	glUseProgram(shaderProgram);
	glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(m_sharedFB.width),
		0.0f, static_cast<float>(m_sharedFB.height),
		-1.0f, 1.0f);
	GLint projLoc = glGetUniformLocation(shaderProgram, "projection");
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

	for (size_t i = sectorMinIndex; i < doubleSector.size(); i++) {
		DoubleSector sector = doubleSector[i];
		float currentStart = std::max(sector.startDuration - static_cast<float>(currentDuration), end_radius);
		float currentEnd = sector.endDuration - static_cast<float>(currentDuration);

		if (currentEnd < end_radius) {
			continue;
		}
		if (currentStart > max_radius) break;

		float angleDiff = sector.angleRange[1] - sector.angleRange[0];
		float borderAngleOuter = (float)std::asin((double)sector.borderRadius / 2 / currentEnd);
		float borderAngleInner = (float)std::asin((double)sector.borderRadius / 2 / currentStart);
		borderAngleOuter = std::min(borderAngleOuter, angleDiff / 2);
		borderAngleInner = std::min(borderAngleInner, angleDiff / 2);

		glBindVertexArray(sector.VAO);

		// 设置统一参数
		glUniform2f(glGetUniformLocation(shaderProgram, "center"), sector.centerX, sector.centerY);
		GLint outerLoc = glGetUniformLocation(shaderProgram, "currentEndRadius");
		GLint innerLoc = glGetUniformLocation(shaderProgram, "currentStartRadius");
		GLint middleColorRadiusLoc = glGetUniformLocation(shaderProgram, "middleColorRadius");
		GLint maxRadiusLoc = glGetUniformLocation(shaderProgram, "maxRadius");

		glUniform1f(innerLoc, currentStart);// 内圈半径
		glUniform1f(outerLoc, currentEnd);  // 外圈半径
		glUniform1f(middleColorRadiusLoc, sector.middleColorLoc * max_radius);
		glUniform1f(maxRadiusLoc, max_radius);

		GLint borderAngleOuterLoc = glGetUniformLocation(shaderProgram, "borderAngleOuter");
		GLint borderAngleInnerLoc = glGetUniformLocation(shaderProgram, "borderAngleInner");
		GLint borderRadiusLoc = glGetUniformLocation(shaderProgram, "borderRadius");
		GLint angleRangeLoc = glGetUniformLocation(shaderProgram, "angleRange");
		glUniform2f(borderAngleOuterLoc, sector.angleRange[0] + borderAngleOuter, sector.angleRange[1] - borderAngleOuter);
		glUniform2f(borderAngleInnerLoc, sector.angleRange[0] + borderAngleInner, sector.angleRange[1] - borderAngleInner);
		glUniform1f(borderRadiusLoc, sector.borderRadius);
		glUniform2f(angleRangeLoc, sector.angleRange[0], sector.angleRange[1]);

		GLint borderBrightnessLoc = glGetUniformLocation(shaderProgram, "borderBrightness");
		GLint centerBrightnessLoc = glGetUniformLocation(shaderProgram, "centerBrightness");

		glUniform1f(borderBrightnessLoc, sector.borderBrightness);
		glUniform1f(centerBrightnessLoc, sector.centerBrightness);

		glm::vec4 color = glm::vec4((float)sector.r, (float)sector.g, (float)sector.b, (float)sector.a) / 255.0f;
		glUniform4f(glGetUniformLocation(shaderProgram, "color"), color.r, color.g, color.b, color.a);
		GLenum err = glGetError();
		if (err != GL_NO_ERROR) {
			std::cerr << "OpenGL Error after setting uniform: 0x" << std::hex << err << std::endl;
		}

		glDrawArrays(GL_TRIANGLE_STRIP, 0, sector.vertexCount);
	}

	// 解析多重采样到纹理
	glBindFramebuffer(GL_READ_FRAMEBUFFER, m_sharedFB.msaaFBO);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_sharedFB.resolveFBO);
	glBlitFramebuffer(0, 0, m_sharedFB.width, m_sharedFB.height,
		0, 0, m_sharedFB.width, m_sharedFB.height,
		GL_COLOR_BUFFER_BIT, GL_LINEAR);

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glDisable(GL_MULTISAMPLE);
}